#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Datetime: 2021/3/16 14:14
# @Author  : CHEN Wang
# @Site    : 
# @File    : indicators_util.py
# @Software: PyCharm 

"""
脚本说明: 技术指标转换成01择时信号的基础函数
"""

import numpy as np
import pandas as pd
import talib as ta
import itertools
from quant_researcher.quant.factors.indicator_tools import indicator_AVGPRICE, indicator_TYPPRICE, indicator_MIDPRICE, indicator_MIDPOINT, indicator_T3, indicator_TEMA, indicator_TRIMA, indicator_KAMA, indicator_MAMA, indicator_EMA, \
    indicator_DEMA, indicator_MA, indicator_HMA, indicator_SMA, indicator_LMA, indicator_VIDYA, indicator_HT_TRENDLINE, indicator_BBI, indicator_DDI, indicator_MACD, indicator_ZLMACD, \
    indicator_PBX, indicator_DMA, indicator_HULLMA, indicator_WC, indicator_MTM, indicator_ADX, indicator_VI, indicator_ADXR, indicator_AROON, indicator_BOP, indicator_CMO, indicator_MFI, \
    indicator_MINUS_DI, indicator_MINUS_DM, indicator_PLUS_DI, indicator_PLUS_DM, indicator_DPO, indicator_ER, indicator_TII, indicator_PPO, indicator_MADisplaced, indicator_POS, indicator_PAC, indicator_Qstick, indicator_FISHER, indicator_DEM, \
    indicator_IC, indicator_TSI, indicator_CLV, indicator_WAD, indicator_PSY, indicator_MICD, indicator_RCCD, indicator_SI, indicator_CV, indicator_KDJ, indicator_KDJD, indicator_SKDJ, indicator_SMI, indicator_STC, indicator_BIAS, indicator_DBCD, \
    indicator_PPO, indicator_ROC, indicator_SROC, indicator_KST, indicator_COPP, indicator_CCI, indicator_DZCCI, indicator_WR, indicator_OSC, indicator_RSI, indicator_DZRSI, indicator_DO, indicator_IMI, indicator_RMI, indicator_RVI, indicator_UOS, \
    indicator_RSIS, indicator_TRIX, indicator_ADTM, indicator_MABIAS, indicator_BOLL, indicator_ENV, indicator_HLC, indicator_KC, indicator_FB, indicator_APZ, indicator_HLMA, indicator_ASI, indicator_VR, \
    indicator_VRSI, indicator_CR, indicator_VSTD, indicator_MAAMT, indicator_SROCVOL, indicator_BIASVOL, indicator_MACDVOL, indicator_ROCVOL, indicator_VWAP, indicator_FI, indicator_NVI, \
    indicator_PVT, indicator_VAO, indicator_RSIV, indicator_AMV, indicator_VRAMT, indicator_WVAD, indicator_AD, indicator_OBV, indicator_CMF, indicator_TMF, indicator_PVI, indicator_KVO, indicator_EMV, indicator_ATR, \
    indicator_NATR, indicator_TRANGE, indicator_HT_DCPERIOD, indicator_HT_DCPHASE, indicator_HT_PHASOR_inphase, indicator_HT_PHASOR_quadrature, indicator_HT_SINE_sine, indicator_HT_SINE_leadsine, indicator_HT_TRENDMODE, indicator_CDL2CROWS, \
    indicator_CDL3BLACKCROWS, indicator_CDL3INSIDE, indicator_CDL3LINESTRIKE, indicator_CDL3OUTSIDE, indicator_CDL3STARSINSOUTH, indicator_CDL3WHITESOLDIERS, indicator_CDLABANDONEDBABY, indicator_CDLADVANCEBLOCK, indicator_CDLBELTHOLD, indicator_CDLBREAKAWAY, \
    indicator_CDLCLOSINGMARUBOZU, indicator_CDLCONCEALBABYSWALL, indicator_CDLCOUNTERATTACK, indicator_CDLDARKCLOUDCOVER, indicator_CDLDOJI, indicator_CDLDOJISTAR, indicator_CDLDRAGONFLYDOJI, indicator_CDLENGULFING, indicator_CDLEVENINGDOJISTAR, \
    indicator_CDLEVENINGSTAR, indicator_CDLGAPSIDESIDEWHITE, indicator_CDLGRAVESTONEDOJI, indicator_CDLHAMMER, indicator_CDLHANGINGMAN, indicator_CDLHARAMI, indicator_CDLHARAMICROSS, indicator_CDLHIGHWAVE, indicator_CDLHIKKAKE, indicator_CDLHIKKAKEMOD, \
    indicator_CDLHOMINGPIGEON, indicator_CDLIDENTICAL3CROWS, indicator_CDLINNECK, indicator_CDLINVERTEDHAMMER, indicator_CDLKICKING, indicator_CDLKICKINGBYLENGTH, indicator_CDLLADDERBOTTOM, indicator_CDLLONGLEGGEDDOJI, indicator_CDLLONGLINE, \
    indicator_CDLMARUBOZU, indicator_CDLMATCHINGLOW, indicator_CDLMATHOLD, indicator_CDLMORNINGDOJISTAR, indicator_CDLMORNINGSTAR, indicator_CDLONNECK, indicator_CDLPIERCING, indicator_CDLRICKSHAWMAN, indicator_CDLRISEFALL3METHODS, \
    indicator_CDLSEPARATINGLINES, indicator_CDLSHOOTINGSTAR, indicator_CDLSHORTLINE, indicator_CDLSPINNINGTOP, indicator_CDLSTALLEDPATTERN, indicator_CDLSTICKSANDWICH, indicator_CDLTAKURI, indicator_CDLTASUKIGAP, indicator_CDLTHRUSTING, indicator_CDLTRISTAR, \
    indicator_CDLUNIQUE3RIVER, indicator_CDLUPSIDEGAP2CROWS, indicator_CDLXSIDEGAP3METHODS
from quant_researcher.quant.factors.indicator_tools.base_series import MA, EMA, REF

method_list = ['enumeration',
               'threshold_mtm_2', 'threshold_mtm_3',
               'threshold_mtm_reversal_4', 'threshold_mtm_reversal_5',
               'sma_cross_minus_2', 'sma_cross_minus_3', 'sma_cross_divide_2', 'sma_cross_divide_3',
               'ema_cross_minus_2', 'ema_cross_minus_3', 'ema_cross_divide_2', 'ema_cross_divide_3',
               'lsma_cross_minus_2', 'lsma_cross_minus_3', 'lsma_cross_divide_2', 'lsma_cross_divide_3',
               'longshort_cross_minus_2', 'longshort_cross_minus_3',
               'longshort_cross_divide_2', 'longshort_cross_divide_3',
               'longshort_mtm_reversal_4', 'longshort_mtm_reversal_5',
               'kline_cross_minus_2', 'kline_cross_divide_2', 'kline_cross_divide_3', 'kline_updown', 'kline_diverge',
               'tangent_2', 'tangent_3']


# # 涨跌幅类指标取值范围一般在-100，+∞；0为特殊点位； 合理取值范围为-100， 5000
# n100_p5000_threshold_neg = [-95, -90, -70, -50, -30, -20, -15, -10, -5]
# n100_p5000_threshold_pos = [5, 10, 15, 20, 30, 50, 70, 90, 100, 120, 150, 200, 300, 500, 1000, 2000, 4000]
# n100_p5000_threshold_2 = n100_p5000_threshold_neg + [0] + n100_p5000_threshold_pos
# n100_p5000_threshold_2_1 = [0]
# n100_p5000_threshold_2_2 = [[i] for i in n100_p5000_threshold_neg + [0] + n100_p5000_threshold_pos]
# n100_p5000_threshold_3_1 = list(itertools.combinations(n100_p5000_threshold_2, 2))
# n100_p5000_threshold_3_2 = list(itertools.product(n100_p5000_threshold_neg, n100_p5000_threshold_pos))
# n100_p5000_threshold_4_1 = list(itertools.combinations(n100_p5000_threshold_2, 3))
# n100_p5000_threshold_4_2 = [i[:1]+(0,)+i[1:] for i in n100_p5000_threshold_3_2]
# n100_p5000_threshold_5_1 = list(itertools.combinations(n100_p5000_threshold_2, 4))
# n100_p5000_threshold_5_2 = list(itertools.product(list(itertools.combinations(n100_p5000_threshold_neg, 2)), list(itertools.combinations(n100_p5000_threshold_pos, 2))))
# n100_p5000_threshold_5_2 = [i[0] + (0,) + i[1] for i in n100_p5000_threshold_5_2]


def get_thereshold_list(value_range="[-100, inf]", threshold_type="2_1"):
    """

    :param value_range:  指标的合理取值范围
    :param threshold_type: 分位点类型
    :return:
    """

    if (value_range == "[-100, 5000]"):
        threshold_left = [-95, -90, -70, -50, -30, -20, -15, -10, -5]
        threshold_right = [5, 10, 15, 20, 30, 50, 70, 90, 100, 120, 150, 200, 300, 500, 1000, 2000, 4000]
        center_point = 0
    elif value_range == "[-100, 100]":
        threshold_left = [-95, -90, -70, -50, -30, -20, -10, -5]
        threshold_right = [5, 10, 20, 30, 50, 70, 90, 95]
        center_point = 0
    elif value_range == "[-500, 500]":
        threshold_left = [-400, -300, -200, -150, -120, -100, -90, -70, -50, -30, -20, -10, -5]
        threshold_right = [5, 10, 20, 30, 50, 70, 90, 100, 120, 150, 200, 300, 400]
        center_point = 0
    elif value_range == "[-200, 300]":
        threshold_left = [-150, -120, -100, -90, -70, -50, -30, -20, -10, 0, 10, 20, 30, 40]
        threshold_right = [60, 70, 90, 100, 120, 140, 180, 200, 250]
        center_point = 50
    elif (value_range == "[0, 500]"):
        threshold_left = [5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95]
        threshold_right = [105, 110, 120, 130, 150, 180, 200, 250, 300, 350, 400]
        center_point = 100
    elif value_range == "[0, 100]":
        threshold_left = [5, 10, 15, 20, 25, 30, 35, 40, 45]
        threshold_right = [55, 60, 65, 70, 75, 80, 85, 90, 95]
        center_point = 50
    elif value_range == "[-inf, inf]":
        bins_list = [[0]]
        return bins_list
    else:
        raise NotImplementedError

    threshold_2 = threshold_left + [center_point] + threshold_right
    if threshold_type == '2_1':
        bins_list = [(center_point,)]
    elif threshold_type == '2_2':
        bins_list = [(i,) for i in threshold_2]
    elif threshold_type == '3_1':
        bins_list = list(itertools.combinations(threshold_2, 2))
    elif threshold_type == '3_2':
        bins_list = list(itertools.product(threshold_left, threshold_right))
    elif threshold_type == '4_1':
        bins_list = list(itertools.combinations(threshold_2, 3))
    elif threshold_type == '4_2':
        bins_list = list(itertools.product(threshold_left, threshold_right))
        bins_list = [i[:1] + (center_point,) + i[1:] for i in bins_list]
    elif threshold_type == '5_1':
        bins_list = list(itertools.combinations(threshold_2, 4))
    elif threshold_type == '5_2':
        bins_list = list(itertools.product(list(itertools.combinations(threshold_left, 2)),
                                           list(itertools.combinations(threshold_right, 2))))
        bins_list = [i[0] + i[1] for i in bins_list]
    else:
        raise NotImplementedError

    return bins_list


threshold_for_method_dict = {"[0, inf]": {'threshold_mtm_2': '',
                                          'threshold_mtm_3': '',
                                          'threshold_mtm_reversal_4': '',
                                          'threshold_mtm_reversal_5': '',
                                          'sma_cross_minus_2': [(0,)],
                                          'sma_cross_minus_3': '',
                                          'sma_cross_divide_2': get_thereshold_list('[-100, 5000]', '2_2'),
                                          'sma_cross_divide_3': get_thereshold_list('[-100, 5000]', '3_2'),
                                          'ema_cross_minus_2': [(0,)],
                                          'ema_cross_minus_3': '',
                                          'ema_cross_divide_2': get_thereshold_list('[-100, 5000]', '2_2'),
                                          'ema_cross_divide_3': get_thereshold_list('[-100, 5000]', '3_2'),
                                          'lsma_cross_minus_2': [(0,)],
                                          'lsma_cross_minus_3': '',
                                          'lsma_cross_divide_2': get_thereshold_list('[-100, 5000]', '2_2'),
                                          'lsma_cross_divide_3': get_thereshold_list('[-100, 5000]', '3_2'),
                                          'longshort_cross_minus_2': [(0,)],
                                          'longshort_cross_minus_3': '',
                                          'longshort_cross_divide_2': get_thereshold_list('[-100, 5000]', '2_2'),
                                          'longshort_cross_divide_3': get_thereshold_list('[-100, 5000]', '3_2'),
                                          'longshort_mtm_reversal_4': '',
                                          'longshort_mtm_reversal_5': '',
                                          'kline_cross_minus_2': [(0,)],
                                          'kline_cross_divide_2': get_thereshold_list('[-100, 5000]', '2_2'),
                                          'kline_cross_divide_3': get_thereshold_list('[-100, 5000]', '3_2'),
                                          'tangent_2': get_thereshold_list('[-100, 100]', '2_2'),
                                          'tangent_3': get_thereshold_list('[-100, 100]', '3_2')},
                             "[-inf, inf]": {'threshold_mtm_2': [(0,)],
                                             'threshold_mtm_3': '',
                                             'threshold_mtm_reversal_4': '',
                                             'threshold_mtm_reversal_5': '',
                                             'sma_cross_minus_2': [(0,)],
                                             'sma_cross_minus_3': '',
                                             'sma_cross_divide_2': '',
                                             'sma_cross_divide_3': '',
                                             'ema_cross_minus_2': [(0,)],
                                             'ema_cross_minus_3': '',
                                             'ema_cross_divide_2': '',
                                             'ema_cross_divide_3': '',
                                             'lsma_cross_minus_2': [(0,)],
                                             'lsma_cross_minus_3': '',
                                             'lsma_cross_divide_2': '',
                                             'lsma_cross_divide_3': '',
                                             'longshort_cross_minus_2': [(0,)],
                                             'longshort_cross_minus_3': '',
                                             'longshort_cross_divide_2': '',
                                             'longshort_cross_divide_3': '',
                                             'longshort_mtm_reversal_4': '',
                                             'longshort_mtm_reversal_5': '',
                                             'kline_cross_minus_2': '',
                                             'kline_cross_divide_2': '',
                                             'kline_cross_divide_3': '',
                                             'tangent_2': get_thereshold_list('[-100, 100]', '2_2'),
                                             'tangent_3': get_thereshold_list('[-100, 100]', '3_2')},
                             "[-100, 100]": {'threshold_mtm_2': get_thereshold_list('[-100, 100]', '2_2'),
                                             'threshold_mtm_3': get_thereshold_list('[-100, 100]', '3_2'),
                                             'threshold_mtm_reversal_4': get_thereshold_list('[-100, 100]', '4_2'),
                                             'threshold_mtm_reversal_5': get_thereshold_list('[-100, 100]', '5_2'),
                                             'sma_cross_minus_2': get_thereshold_list('[-100, 100]', '2_2'),
                                             'sma_cross_minus_3': get_thereshold_list('[-100, 100]', '3_2'),
                                             'sma_cross_divide_2': '',
                                             'sma_cross_divide_3': '',
                                             'ema_cross_minus_2': get_thereshold_list('[-100, 100]', '2_2'),
                                             'ema_cross_minus_3': get_thereshold_list('[-100, 100]', '3_2'),
                                             'ema_cross_divide_2': '',
                                             'ema_cross_divide_3': '',
                                             'lsma_cross_minus_2': get_thereshold_list('[-100, 100]', '2_2'),
                                             'lsma_cross_minus_3': get_thereshold_list('[-100, 100]', '3_2'),
                                             'lsma_cross_divide_2': '',
                                             'lsma_cross_divide_3': '',
                                             'longshort_cross_minus_2': get_thereshold_list('[-100, 100]', '2_2'),
                                             'longshort_cross_minus_3': get_thereshold_list('[-100, 100]', '3_2'),
                                             'longshort_cross_divide_2': '',
                                             'longshort_cross_divide_3': '',
                                             'longshort_mtm_reversal_4': get_thereshold_list('[-100, 100]', '4_2'),
                                             'longshort_mtm_reversal_5': get_thereshold_list('[-100, 100]', '5_2'),
                                             'kline_cross_minus_2': '',
                                             'kline_cross_divide_2': '',
                                             'kline_cross_divide_3': '',
                                             'tangent_2': get_thereshold_list('[-100, 100]', '2_2'),
                                             'tangent_3': get_thereshold_list('[-100, 100]', '3_2')},
                             "[0, 100]": {'threshold_mtm_2': get_thereshold_list('[0, 100]', '2_2'),
                                          'threshold_mtm_3': get_thereshold_list('[0, 100]', '3_2'),
                                          'threshold_mtm_reversal_4': get_thereshold_list('[0, 100]', '4_2'),
                                          'threshold_mtm_reversal_5': get_thereshold_list('[0, 100]', '5_2'),
                                          'sma_cross_minus_2': get_thereshold_list('[-100, 100]', '2_2'),
                                          'sma_cross_minus_3': get_thereshold_list('[-100, 100]', '3_2'),
                                          'sma_cross_divide_2': '',
                                          'sma_cross_divide_3': '',
                                          'ema_cross_minus_2': get_thereshold_list('[-100, 100]', '2_2'),
                                          'ema_cross_minus_3': get_thereshold_list('[-100, 100]', '3_2'),
                                          'ema_cross_divide_2': '',
                                          'ema_cross_divide_3': '',
                                          'lsma_cross_minus_2': get_thereshold_list('[-100, 100]', '2_2'),
                                          'lsma_cross_minus_3': get_thereshold_list('[-100, 100]', '3_2'),
                                          'lsma_cross_divide_2': '',
                                          'lsma_cross_divide_3': '',
                                          'longshort_cross_minus_2': get_thereshold_list('[-100, 100]', '2_2'),
                                          'longshort_cross_minus_3': get_thereshold_list('[-100, 100]', '3_2'),
                                          'longshort_cross_divide_2': '',
                                          'longshort_cross_divide_3': '',
                                          'longshort_mtm_reversal_4': get_thereshold_list('[0, 100]', '4_2'),
                                          'longshort_mtm_reversal_5': get_thereshold_list('[0, 100]', '5_2'),
                                          'kline_cross_minus_2': '',
                                          'kline_cross_divide_2': '',
                                          'kline_cross_divide_3': '',
                                          'tangent_2': get_thereshold_list('[-100, 100]', '2_2'),
                                          'tangent_3': get_thereshold_list('[-100, 100]', '3_2')},
                             "[-200, 300]": {'threshold_mtm_2': get_thereshold_list('[-200, 300]', '2_2'),
                                             'threshold_mtm_3': get_thereshold_list('[-200, 300]', '3_2'),
                                             'threshold_mtm_reversal_4': get_thereshold_list('[-200, 300]', '4_2'),
                                             'threshold_mtm_reversal_5': get_thereshold_list('[-200, 300]', '5_2'),
                                             'tangent_2': get_thereshold_list('[-100, 100]', '2_2'),
                                             'tangent_3': get_thereshold_list('[-100, 100]', '3_2')},
                             "[-100, 5000]": {'threshold_mtm_2': get_thereshold_list('[-100, 5000]', '2_2'),
                                              'threshold_mtm_3': get_thereshold_list('[-100, 5000]', '3_2'),
                                              'threshold_mtm_reversal_4': get_thereshold_list('[-100, 5000]', '4_2'),
                                              'threshold_mtm_reversal_5': get_thereshold_list('[-100, 5000]', '5_2'),
                                              'sma_cross_minus_2': get_thereshold_list('[-500, 500]', '2_2'),
                                              'sma_cross_minus_3': get_thereshold_list('[-500, 500]', '3_2'),
                                              'sma_cross_divide_2': '',
                                              'sma_cross_divide_3': '',
                                              'ema_cross_minus_2': get_thereshold_list('[-500, 500]', '2_2'),
                                              'ema_cross_minus_3': get_thereshold_list('[-500, 500]', '3_2'),
                                              'ema_cross_divide_2': '',
                                              'ema_cross_divide_3': '',
                                              'lsma_cross_minus_2': get_thereshold_list('[-500, 500]', '2_2'),
                                              'lsma_cross_minus_3': get_thereshold_list('[-500, 500]', '3_2'),
                                              'lsma_cross_divide_2': '',
                                              'lsma_cross_divide_3': '',
                                              'longshort_cross_minus_2': get_thereshold_list('[-500, 500]', '2_2'),
                                              'longshort_cross_minus_3': get_thereshold_list('[-500, 500]', '3_2'),
                                              'longshort_cross_divide_2': '',
                                              'longshort_cross_divide_3': '',
                                              'longshort_mtm_reversal_4': get_thereshold_list('[-100, 5000]', '4_2'),
                                              'longshort_mtm_reversal_5': get_thereshold_list('[-100, 5000]', '5_2'),
                                              'kline_cross_minus_2': '',
                                              'kline_cross_divide_2': '',
                                              'kline_cross_divide_3': '',
                                              'tangent_2': get_thereshold_list('[-100, 100]', '2_2'),
                                              'tangent_3': get_thereshold_list('[-100, 100]', '3_2')},
                             "[-500, 500]": {'threshold_mtm_2': get_thereshold_list('[-500, 500]', '2_2'),
                                             'threshold_mtm_3': get_thereshold_list('[-500, 500]', '3_2'),
                                             'threshold_mtm_reversal_4': get_thereshold_list('[-500, 500]', '4_2'),
                                             'threshold_mtm_reversal_5': get_thereshold_list('[-500, 500]', '5_2'),
                                             'sma_cross_minus_2': '',
                                             'sma_cross_minus_3': '',
                                             'sma_cross_divide_2': '',
                                             'sma_cross_divide_3': '',
                                             'ema_cross_minus_2': '',
                                             'ema_cross_minus_3': '',
                                             'ema_cross_divide_2': '',
                                             'ema_cross_divide_3': '',
                                             'lsma_cross_minus_2': '',
                                             'lsma_cross_minus_3': '',
                                             'lsma_cross_divide_2': '',
                                             'lsma_cross_divide_3': '',
                                             'longshort_cross_minus_2': '',
                                             'longshort_cross_minus_3': '',
                                             'longshort_cross_divide_2': '',
                                             'longshort_cross_divide_3': '',
                                             'longshort_mtm_reversal_4': '',
                                             'longshort_mtm_reversal_5': '',
                                             'kline_cross_minus_2': '',
                                             'kline_cross_divide_2': '',
                                             'kline_cross_divide_3': '',
                                             'tangent_2': get_thereshold_list('[-100, 100]', '2_2'),
                                             'tangent_3': get_thereshold_list('[-100, 100]', '3_2')},
                             "[0, 500]": {'threshold_mtm_2': get_thereshold_list('[0, 500]', '2_2'),
                                          'threshold_mtm_3': get_thereshold_list('[0, 500]', '3_2'),
                                          'threshold_mtm_reversal_4': get_thereshold_list('[0, 500]', '4_2'),
                                          'threshold_mtm_reversal_5': get_thereshold_list('[0, 500]', '5_2'),
                                          'sma_cross_minus_2': get_thereshold_list('[-500, 500]', '2_2'),
                                          'sma_cross_minus_3': get_thereshold_list('[-500, 500]', '3_2'),
                                          'sma_cross_divide_2': '',
                                          'sma_cross_divide_3': '',
                                          'ema_cross_minus_2': '',
                                          'ema_cross_minus_3': '',
                                          'ema_cross_divide_2': '',
                                          'ema_cross_divide_3': '',
                                          'lsma_cross_minus_2': '',
                                          'lsma_cross_minus_3': '',
                                          'lsma_cross_divide_2': '',
                                          'lsma_cross_divide_3': '',
                                          'longshort_cross_minus_2': '',
                                          'longshort_cross_minus_3': '',
                                          'longshort_cross_divide_2': '',
                                          'longshort_cross_divide_3': '',
                                          'longshort_mtm_reversal_4': '',
                                          'longshort_mtm_reversal_5': '',
                                          'kline_cross_minus_2': '',
                                          'kline_cross_divide_2': '',
                                          'kline_cross_divide_3': '',
                                          'tangent_2': get_thereshold_list('[-100, 100]', '2_2'),
                                          'tangent_3': get_thereshold_list('[-100, 100]', '3_2')},
                             "[10, 500]": {'threshold_mtm_2': '',
                                           'threshold_mtm_3': '',
                                           'threshold_mtm_reversal_4': '',
                                           'threshold_mtm_reversal_5': '',
                                           'sma_cross_minus_2': '',
                                           'sma_cross_minus_3': '',
                                           'sma_cross_divide_2': '',
                                           'sma_cross_divide_3': '',
                                           'ema_cross_minus_2': '[(0,)]',
                                           'ema_cross_minus_3': '',
                                           'ema_cross_divide_2': '',
                                           'ema_cross_divide_3': '',
                                           'lsma_cross_minus_2': '[(0,)]',
                                           'lsma_cross_minus_3': '',
                                           'lsma_cross_divide_2': '',
                                           'lsma_cross_divide_3': '',
                                           'longshort_cross_minus_2': '',
                                           'longshort_cross_minus_3': '',
                                           'longshort_cross_divide_2': '',
                                           'longshort_cross_divide_3': '',
                                           'longshort_mtm_reversal_4': '',
                                           'longshort_mtm_reversal_5': '',
                                           'kline_cross_minus_2': '',
                                           'kline_cross_divide_2': '',
                                           'kline_cross_divide_3': '',
                                           'tangent_2': get_thereshold_list('[-100, 100]', '2_2'),
                                           'tangent_3': get_thereshold_list('[-100, 100]', '3_2')},
                             }


def enumeration(ts, **kwargs):
    """
    技术指标的取数只为某几个特殊值，根据特殊值直接转变为信号

    :param pd.Sereis ts: 指标值
    :return: pd.Sereis
    """

    positive = kwargs.pop('positive', True)  # 指标值越大越好还是越小越好
    if len(ts.unique()) == 1:  # 指标取值只有一种
        signal = ts.copy()
        if positive:
            signal[:] = 1
        else:
            signal[:] = 0
    elif len(ts.unique()) in [2, 3]:  # 指标取值只有两种或三种状态
        signal = ts.copy()
        if positive:
            signal[ts == ts.max()] = 'buy'
            signal[ts == ts.min()] = 'sell'
        else:
            signal[ts == ts.max()] = 'sell'
            signal[ts == ts.min()] = 'buy'
        signal[(signal != 'sell') & (signal != 'buy')] = np.nan
        signal.fillna(method='ffill', inplace=True)  # 后面的NaN用前值填充
        signal.dropna(inplace=True)  # 前面的NaN直接踢掉
        signal[signal == 'buy'] = 1
        signal[signal == 'sell'] = 0

    elif len(ts.unique()) == 5:  # 指标取值只有五种状态
        unique_list = list(ts.unique())
        unique_list.sort()
        signal = ts.copy()
        if positive:
            signal[(ts == unique_list[-1]) | (ts == unique_list[-2])] = 'buy'
            signal[(ts == unique_list[0]) | (ts == unique_list[1])] = 'sell'
        else:
            signal[(ts == unique_list[-1]) | (ts == unique_list[-2])] = 'sell'
            signal[(ts == unique_list[0]) | (ts == unique_list[1])] = 'buy'
        signal[(signal != 'sell') & (signal != 'buy')] = np.nan
        signal.fillna(method='ffill', inplace=True)  # 后面的NaN用前值填充
        signal.dropna(inplace=True)  # 前面的NaN直接踢掉
        signal[signal == 'buy'] = 1
        signal[signal == 'sell'] = 0
    else:
        raise ValueError

    signal.name = ts.name + f'-enumeration'
    return signal


def sma_cross_minus(ts, **kwargs):
    util_sma_period = kwargs.pop('util_period')
    res = ts - MA(ts, util_sma_period)
    res.name = ts.name + f'-sma_cross_minus-{util_sma_period}'
    return res


def sma_cross_divide(ts, **kwargs):
    util_sma_period = kwargs.pop('util_period')
    res = (ts - MA(ts, util_sma_period)) / MA(ts, util_sma_period) * 100
    res.name = ts.name + f'-sma_cross_divide-{util_sma_period}'
    return res


def ema_cross_minus(ts, **kwargs):
    util_ema_period = kwargs.pop('util_period')
    res = ts - EMA(ts, util_ema_period)
    res.name = ts.name + f'-ema_cross_minus-{util_ema_period}'
    return res


def ema_cross_divide(ts, **kwargs):
    util_ema_period = kwargs.pop('util_period')
    res = (ts - EMA(ts, util_ema_period)) / EMA(ts, util_ema_period) * 100
    res.name = ts.name + f'-ema_cross_divide-{util_ema_period}'
    return res


def lsma_cross_minus(ts, **kwargs):
    util_lsma_period = kwargs.pop('util_period')
    res = MA(ts, util_lsma_period[0]) - MA(ts, util_lsma_period[1])
    res.name = ts.name + f'-lsma_cross_minus-{util_lsma_period}'
    return res


def lsma_cross_divide(ts, **kwargs):
    util_lsma_period = kwargs.pop('util_period')
    res = (MA(ts, util_lsma_period[0]) - MA(ts, util_lsma_period[1])) / MA(ts, util_lsma_period[1]) * 100
    res.name = ts.name + f'-lsma_cross_divide-{util_lsma_period}'
    return res


def longshort_cross_minus(short_ts, long_ts, **kwargs):
    util_short_long_period = kwargs.pop('util_period')
    res = short_ts - long_ts
    res.name = short_ts.name + f'-longshort_cross_minus-{util_short_long_period}'
    return res


def longshort_cross_divide(short_ts, long_ts, **kwargs):
    util_short_long_period = kwargs.pop('util_period')
    res = (short_ts - long_ts) / long_ts * 100
    res.name = short_ts.name + f'-longshort_cross_divide-{util_short_long_period}'
    return res


def kline_cross_minus(ts, ohlcv_data, **kwargs):
    res = ohlcv_data.close - ts
    res.name = ts.name + f'-kline_cross_minus'
    return res


def kline_cross_divide(ts, ohlcv_data, **kwargs):
    res = (ohlcv_data.close - ts) / ts * 100
    res.name = ts.name + f'-kline_cross_divide'
    return res


def tangent(ts, **kwargs):
    util_tangent_period = kwargs.pop('util_period')
    res = MA(np.sign(ts - REF(ts, 1)), util_tangent_period) * 100
    res.name = ts.name + f'-tangent-{util_tangent_period}'
    return res


def macd_signal(data, fastperiod=12, slowperiod=26, signalperiod=9, positive=True):
    """
    返回根据macd指标生成的信号序列
    :param positive: 信号方向
    :param pd.Series data: 收盘价数据，datetime索引
    :param fastperiod:
    :param slowperiod:
    :param signalperiod:
    :return: 返回信号序列，满仓为1，空仓为-1
    """
    _, MACDsignal, _ = ta.MACD(data['close'], fastperiod=fastperiod, slowperiod=slowperiod,
                               signalperiod=signalperiod)
    signal = MACDsignal.copy()
    signal.loc[(MACDsignal >= 0).shift().bfill()] = 1
    signal.loc[MACDsignal < 0] = -1
    signal = signal.where(signal.abs() == 1).ffill()
    if not positive:
        signal = - signal
    return signal


def kdj_signal(data, fastk_period=9, slowk_period=3, slowk_matype=0, slowd_period=3, slowd_matype=0,
               positive=True):
    """
    返回根据kdj指标生成的信号序列
    :param positive:信号方向
    :param data: 最高价，datetime索引
    :param fastk_period:
    :param slowk_period:
    :param slowk_matype:
    :param slowd_period:
    :param slowd_matype:
    :return: 返回信号序列，满仓为1，空仓为-1
    """
    k, d = ta.STOCH(data['high'], data['low'], data['close'],
                    fastk_period=fastk_period, slowk_period=slowk_period,
                    slowk_matype=slowk_matype, slowd_period=slowd_period,
                    slowd_matype=slowd_matype)
    j = 3 * k - 2 * d
    out = pd.concat([k, d, j], axis=1)
    out.columns = ['k', 'd', 'j']
    signal = k.copy()
    signal.loc[(out['k'] - out['d'] >= 0).shift().bfill()] = 1
    signal.loc[out['k'] - out['d'] < 0] = -1
    signal = signal.where(signal.abs() == 1).ffill()
    if not positive:
        signal = - signal
    return signal


def rsi_signal(data, timeperiod=14, up=70, down=30, positive=True):
    """
    返回根据rsi指标生成的信号序列
    :param positive:信号方向
    :param data: 收盘价，datetime索引
    :param timeperiod:
    :param up: 超买阈值
    :param down: 超卖阈值
    :return: 返回由rsi指标生成的信号序列
    """
    tarsi = ta.RSI(data['close'], timeperiod=timeperiod)
    signal = tarsi.copy()
    signal.loc[(tarsi >= up).shift().bfill()] = -1
    signal.loc[tarsi <= down] = 1
    signal = signal.where(signal.abs() == 1).ffill()
    if not positive:
        signal = - signal
    return signal


def wr_signal(data, timeperiod=14, up=80, down=20, positive=True):
    """

    :param positive:信号方向
    :param data: 最高价，datetime索引
    :param timeperiod:
    :param up:
    :param down:
    :return: 返回由威廉指标生成的信号序列
    """
    tawr = ta.WILLR(data['high'], data['low'], data['close'], timeperiod=timeperiod)
    signal = tawr.copy()
    signal.loc[(tawr >= up).shift().bfill()] = 1
    signal.loc[tawr <= down] = -1
    signal = signal.where(signal.abs() == 1).ffill()
    if not positive:
        signal = - signal
    return signal


def bband_signal(data, timeperiod=60, nbdevup=2, nbdevdn=2, matype=0, positive=True):
    """

    :param positive:信号方向
    :param data: 收盘价，datetime索引
    :param timeperiod: 均线周期
    :param nbdevup: 往上偏离几倍标准差
    :param nbdevdn: 往下偏离几倍标准差
    :param matype: 均线计算方式
    :return:  返回由布林带生成的信号序列
    """
    if isinstance(data, pd.DataFrame):
        ts = data['close']
    elif isinstance(data, pd.Series):
        ts = data

    upperband, middleband, lowerband = ta.BBANDS(ts, timeperiod=timeperiod,
                                                 nbdevup=nbdevup, nbdevdn=nbdevdn, matype=matype)
    signal = upperband.copy()
    signal.loc[(ts >= upperband).shift().bfill()] = -1
    signal.loc[ts <= lowerband] = 1
    signal = signal.where(signal.abs() == 1).ffill()  # 其他非信号部分延续之前的信号
    if not positive:
        signal = - signal
    return signal


def bband_score(data, k=2, period=60, positive=True, scale=10):
    data = data.T.squeeze()
    if data.unique().shape[0] == 1:
        return pd.Series([np.nan for i in range(len(data))], index=data.index)
    moving_mean = data.rolling(period).mean()
    std = data.rolling(period).std()
    result = (data - moving_mean) / std
    if not positive:
        result = -result
    # test = bband_to_value(data, period, positive)
    score = (k - result) / (2 * k)
    score = score.clip(lower=0, upper=1) * scale
    return score.round()


def ema_cross_signal(data, short_period=5, long_period=20, positive=True):
    """
    指数移动平均交叉
    :param positive:信号方向
    :param data: 收盘价，datetime索引
    :param short_period: 短期均线时长
    :param long_period: 长期均线时长
    :return: 返回由指数移动平均交叉生成的信号
    """
    ema_short = ta.EMA(data['close'], timeperiod=short_period)
    ema_long = ta.EMA(data['close'], timeperiod=long_period)
    signal = ema_short.copy()
    signal.loc[(ema_short >= ema_long).shift().bfill()] = 1
    signal.loc[ema_short < ema_long] = -1
    signal = signal.where(signal.abs() == 1).ffill()
    if not positive:
        signal = - signal
    return signal


def ma_cross_signal(data, short_period=20, long_period=60, positive=True):
    """
    简单移动平均交叉转换成信号，短均线上穿长均线为1，短均线下穿长均线为-1

    :param data: 收盘价，datetime索引
    :param short_period: 短期均线时长
    :param long_period: 长期均线时长
    :param positive:信号方向
    :return: 返回由移动平均交叉生成的信号, **** 注意这里的信号是已经shift了一期 ****
    """

    if isinstance(data, pd.DataFrame):
        ts = data['close']
    elif isinstance(data, pd.Series):
        ts = data

    ma_short = ta.MA(ts, timeperiod=short_period)  # 计算短均线
    ma_long = ta.MA(ts, timeperiod=long_period)  # 计算长均线

    # 剔除因计算均线得到的NA值
    ma_long.dropna(inplace=True)
    ma_short = ma_short[ma_long.index[0]:]

    # 计算得到信号
    signal = (ma_short >= ma_long).shift()
    signal.dropna(inplace=True)  # 因为滞后一期所以第一期无信号

    # 信号转换成1和-1
    signal = signal.astype(int)
    signal[signal == 0] = -1

    if not positive:
        signal = - signal
    return signal


def ma_score(data, short_period=20, long_period=60, positive=True, scale=10):
    """
    简单移动平均交叉转换成得分，根据长短均线的距离计算得分

    :param data: 收盘价，datetime索引
    :param short_period: 短期均线时长
    :param long_period: 长期均线时长
    :param positive:信号方向
    :return: 返回由移动平均交叉生成的信号, **** 注意这里的信号是已经shift了一期 ****
    """

    # todo 下面的得分转换是利用的未来数据，需要修改
    data = data.T.squeeze()
    if data.unique().shape[0] == 1:
        return pd.Series([np.nan for i in range(len(data))], index=data.index)
    ma_short = data.rolling(short_period).mean()
    ma_long = data.rolling(long_period).mean()

    # 剔除因计算均线得到的NA值
    ma_long.dropna(inplace=True)
    ma_short = ma_short[ma_long.index[0]:]

    signal_raw = (ma_short - ma_long).shift()
    signal_raw.dropna(inplace=True)  # 因为滞后一期所以第一期无得分

    if not positive:
        signal_raw = -signal_raw
    test_sign = signal_raw.round(6) > 0
    change_point = signal_raw[test_sign != test_sign.shift()].index
    change_point = change_point.append(signal_raw.index[-1:])
    test_abs = signal_raw.abs()
    result = []
    for end, start in zip(change_point[1:], change_point[:-1]):
        temp = test_abs.loc[start:end].iloc[:-1]
        relaitive_value = temp / temp.cummax()
        result.append(relaitive_value)
    result_df = pd.concat(result)
    result_df.loc[~test_sign] = 1 - result_df.loc[~test_sign]
    result_df = result_df * scale
    return result_df.round()


ta_func_list = [indicator_AVGPRICE, indicator_TYPPRICE, indicator_MIDPRICE, indicator_MIDPOINT, indicator_T3,
                indicator_TEMA, indicator_TRIMA, indicator_KAMA, indicator_MAMA, indicator_EMA,
                indicator_DEMA, indicator_MA, indicator_HMA, indicator_SMA, indicator_LMA,
                indicator_VIDYA, indicator_HT_TRENDLINE, indicator_BBI, indicator_DDI,
                indicator_MACD, indicator_ZLMACD, indicator_PBX, indicator_DMA,
                indicator_HULLMA, indicator_WC, indicator_MTM, indicator_ADX,
                indicator_VI, indicator_ADXR, indicator_AROON, indicator_BOP, indicator_CMO,
                indicator_MFI, indicator_MINUS_DI, indicator_MINUS_DM, indicator_PLUS_DI,
                indicator_PLUS_DM, indicator_DPO, indicator_ER, indicator_TII, indicator_PPO,
                indicator_MADisplaced, indicator_POS, indicator_PAC, indicator_Qstick, indicator_FISHER,
                indicator_DEM, indicator_IC, indicator_TSI, indicator_CLV, indicator_WAD, indicator_PSY,
                indicator_MICD, indicator_RCCD, indicator_SI, indicator_CV, indicator_KDJ,
                indicator_KDJD, indicator_SKDJ, indicator_SMI, indicator_STC, indicator_BIAS,
                indicator_DBCD, indicator_PPO, indicator_ROC, indicator_SROC, indicator_KST, indicator_COPP,
                indicator_CCI, indicator_DZCCI, indicator_WR, indicator_OSC, indicator_RSI,
                indicator_DZRSI, indicator_DO, indicator_IMI, indicator_RMI, indicator_RVI,
                indicator_UOS, indicator_RSIS, indicator_TRIX,
                indicator_ADTM, indicator_MABIAS, indicator_BOLL, indicator_ENV, indicator_HLC,
                indicator_KC, indicator_FB, indicator_APZ, indicator_HLMA, indicator_ASI,
                indicator_VR, indicator_VRSI, indicator_CR,
                indicator_VSTD, indicator_MAAMT, indicator_SROCVOL,
                indicator_BIASVOL, indicator_MACDVOL, indicator_ROCVOL, indicator_VWAP, indicator_FI, indicator_NVI,
                indicator_PVT, indicator_VAO, indicator_RSIV, indicator_AMV, indicator_VRAMT, indicator_WVAD,
                indicator_AD, indicator_OBV, indicator_CMF, indicator_TMF, indicator_PVI,
                indicator_KVO, indicator_EMV, indicator_ATR, indicator_NATR, indicator_TRANGE,
                indicator_HT_DCPERIOD, indicator_HT_DCPHASE, indicator_HT_PHASOR_inphase, indicator_HT_PHASOR_quadrature,
                indicator_HT_SINE_sine, indicator_HT_SINE_leadsine, indicator_HT_TRENDMODE,
                indicator_CDL2CROWS, indicator_CDL3BLACKCROWS, indicator_CDL3INSIDE, indicator_CDL3LINESTRIKE,
                indicator_CDL3OUTSIDE, indicator_CDL3STARSINSOUTH, indicator_CDL3WHITESOLDIERS,
                indicator_CDLABANDONEDBABY, indicator_CDLADVANCEBLOCK, indicator_CDLBELTHOLD,
                indicator_CDLBREAKAWAY, indicator_CDLCLOSINGMARUBOZU, indicator_CDLCONCEALBABYSWALL,
                indicator_CDLCOUNTERATTACK, indicator_CDLDARKCLOUDCOVER, indicator_CDLDOJI,
                indicator_CDLDOJISTAR, indicator_CDLDRAGONFLYDOJI, indicator_CDLENGULFING,
                indicator_CDLEVENINGDOJISTAR, indicator_CDLEVENINGSTAR, indicator_CDLGAPSIDESIDEWHITE,
                indicator_CDLGRAVESTONEDOJI, indicator_CDLHAMMER, indicator_CDLHANGINGMAN, indicator_CDLHARAMI,
                indicator_CDLHARAMICROSS, indicator_CDLHIGHWAVE, indicator_CDLHIKKAKE, indicator_CDLHIKKAKEMOD,
                indicator_CDLHOMINGPIGEON, indicator_CDLIDENTICAL3CROWS, indicator_CDLINNECK,
                indicator_CDLINVERTEDHAMMER, indicator_CDLKICKING, indicator_CDLKICKINGBYLENGTH,
                indicator_CDLLADDERBOTTOM, indicator_CDLLONGLEGGEDDOJI, indicator_CDLLONGLINE,
                indicator_CDLMARUBOZU, indicator_CDLMATCHINGLOW, indicator_CDLMATHOLD,
                indicator_CDLMORNINGDOJISTAR, indicator_CDLMORNINGSTAR, indicator_CDLONNECK,
                indicator_CDLPIERCING, indicator_CDLRICKSHAWMAN, indicator_CDLRISEFALL3METHODS,
                indicator_CDLSEPARATINGLINES, indicator_CDLSHOOTINGSTAR, indicator_CDLSHORTLINE,
                indicator_CDLSPINNINGTOP, indicator_CDLSTALLEDPATTERN, indicator_CDLSTICKSANDWICH,
                indicator_CDLTAKURI, indicator_CDLTASUKIGAP, indicator_CDLTHRUSTING, indicator_CDLTRISTAR,
                indicator_CDLUNIQUE3RIVER, indicator_CDLUPSIDEGAP2CROWS, indicator_CDLXSIDEGAP3METHODS]
enumerate_method = ['enumeration']
threshold_mtm_method_1 = ['threshold_mtm_2']
threshold_mtm_method_2 = ['threshold_mtm_2', 'threshold_mtm_3']
threshold_mtm_reversal_method = ['threshold_mtm_reversal_4', 'threshold_mtm_reversal_5']
sma_method_1 = ['sma_cross_minus_2']
sma_method_2 = ['sma_cross_minus_2', 'sma_cross_minus_3']
sma_method_3 = ['sma_cross_minus_2', 'sma_cross_divide_2', 'sma_cross_divide_3']
sma_method_4 = ['sma_cross_minus_2', 'sma_cross_minus_3', 'sma_cross_divide_2', 'sma_cross_divide_3']
ema_method_1 = ['ema_cross_minus_2']
ema_method_2 = ['ema_cross_minus_2', 'ema_cross_minus_3']
ema_method_3 = ['ema_cross_minus_2', 'ema_cross_divide_2', 'ema_cross_divide_3']
ema_method_4 = ['ema_cross_minus_2', 'ema_cross_minus_3', 'ema_cross_divide_2', 'ema_cross_divide_3']
lsma_method_1 = ['lsma_cross_minus_2']
lsma_method_2 = ['lsma_cross_minus_2', 'lsma_cross_minus_3']
lsma_method_3 = ['lsma_cross_minus_2', 'lsma_cross_divide_2', 'lsma_cross_divide_3']
lsma_method_4 = ['lsma_cross_minus_2', 'lsma_cross_minus_3', 'lsma_cross_divide_2', 'lsma_cross_divide_3']
ls_cross_method_1 = ['longshort_cross_minus_2']
ls_cross_method_2 = ['longshort_cross_minus_2', 'longshort_cross_minus_3']
ls_cross_method_3 = ['longshort_cross_minus_2', 'longshort_cross_divide_2', 'longshort_cross_divide_3']
ls_cross_method_4 = ['longshort_cross_minus_2', 'longshort_cross_minus_3', 'longshort_cross_divide_2',
                     'longshort_cross_divide_3']
ls_mtm_reversal_method = ['longshort_mtm_reversal_4', 'longshort_mtm_reversal_5']
kline_cross_method_1 = ['kline_cross_minus_2', 'kline_cross_divide_2', 'kline_cross_divide_3']
kline_cross_method_2 = ['kline_cross_minus_2', 'kline_cross_minus_3', 'kline_cross_divide_2', 'kline_cross_divide_3']
kline_special_method = ['kline_updown', 'kline_diverge']
tangent_method = ['tangent_2', 'tangent_3']
holding_pct = ['holding_pct']
method_0_inf_1 = sma_method_3 + lsma_method_3 + kline_cross_method_1 + tangent_method
method_0_inf_2 = sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method
method_0_inf_3 = sma_method_3 + ls_cross_method_3 + tangent_method
ta_func_util_dict = {
    'indicator_AVGPRICE': {'indic_type': 'price', 'value_range': '[0, inf]', 'reasonable_range': '[0, inf]', 'center_point': '',
                           'method': sma_method_3 + lsma_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_TYPPRICE': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                           'method': sma_method_3 + lsma_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_MIDPRICE': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                           'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_MIDPOINT': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                           'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_T3': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                     'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_TEMA': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                       'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_TRIMA': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                        'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_KAMA': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                       'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_MAMA': {'indic_type': 'price', 'value_range': '[0, inf]', 'reasonable_range': '[0, inf]', 'center_point': '',
                       'method': sma_method_3 + lsma_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_WMA': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                      'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_EMA': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                      'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_DEMA': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                       'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_MA': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                     'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_HMA': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                      'method': sma_method_3 + ls_cross_method_3 + tangent_method},
    'indicator_HMACROSS': {'indic_type': 'price_diff', 'value_range': "[-inf, inf]", 'reasonable_range': '[-inf, inf]', 'center_point': 0,
                           'method': threshold_mtm_method_1 + sma_method_1 + tangent_method},
    'indicator_SMA': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                      'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_LMA': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                      'method': sma_method_3 + ls_cross_method_3 + tangent_method},
    'indicator_LMACROSS': {'indic_type': 'price_diff', 'value_range': "[-inf, inf]", 'reasonable_range': '[-inf, inf]', 'center_point': 0,
                           'method': threshold_mtm_method_1 + sma_method_1 + tangent_method},
    'indicator_VIDYA': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                        'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_HT_TRENDLINE': {'indic_type': 'price', 'value_range': '[0, inf]', 'reasonable_range': '[0, inf]', 'center_point': '',
                               'method': sma_method_3 + lsma_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_BBI': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                      'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_DDI': {'indic_type': 'ratio_diff', 'value_range': '[-100, 100]', 'reasonable_range': '[-100, 100]', 'center_point': 0,
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    # todo MACD的使用方法是不是可以更多？
    'indicator_MACD': {'indic_type': 'price_diff', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]', 'center_point': 0,
                       'method': threshold_mtm_method_1 + tangent_method},
    'indicator_ZLMACD': {'indic_type': 'price_diff', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]', 'center_point': 0,
                         'method': threshold_mtm_method_1 + tangent_method},
    # todo DMI的特殊使用法需要补充
    'indicator_DMI_DI': {'indic_type': 'ratio_diff', 'value_range': '[-100, 100]', 'reasonable_range': '[-100, 100]', 'center_point': 0,
                         'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_DMI_AD': {'indic_type': 'ratio_diff', 'value_range': '[-100, 100]', 'reasonable_range': '[-100, 100]', 'center_point': 0,
                         'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method},
    # todo PBX的特殊使用法需要补充
    'indicator_PBX': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                      'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    # todo DMA的特殊使用法需要补充
    'indicator_DMA': {'indic_type': 'price_diff', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]', 'center_point': 0,
                      'method': threshold_mtm_method_1 + sma_method_1 + tangent_method},
    'indicator_EXPMA': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                        'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_HULLMA': {'indic_type': 'price_diff', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]', 'center_point': 0,
                         'method': threshold_mtm_method_1 + sma_method_1 + tangent_method},
    'indicator_WC': {'indic_type': 'price_diff', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]', 'center_point': 0,
                     'method': threshold_mtm_method_1 + sma_method_1 + tangent_method},
    'indicator_MTM': {'indic_type': 'price_diff', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]', 'center_point': 0,
                      'method': threshold_mtm_method_1 + sma_method_1 + tangent_method},
    'indicator_CHO': {'indic_type': 'volume_diff', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]', 'center_point': 0,
                      'method': threshold_mtm_method_1 + sma_method_1 + tangent_method},
    'indicator_ADX': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]', 'center_point': 50,
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_VI': {'indic_type': '', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]', 'center_point': 0,
                     'method': threshold_mtm_method_1 + sma_method_1 + tangent_method},
    'indicator_RWI': {'indic_type': '', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_ADXR': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                       'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                 ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_AROONOSC': {'indic_type': 'ratio_diff', 'value_range': '[-100, 100]', 'reasonable_range': '[-100, 100]',
                           'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct +
                                     tangent_method},
    'indicator_BOP': {'indic_type': 'ratio', 'value_range': '[-100, 100]', 'reasonable_range': '[-100, 100]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_CMO': {'indic_type': 'ratio_diff', 'value_range': '[-100, 100]', 'reasonable_range': '[-100, 100]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_DX': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                     'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                               ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_MFI': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_MINUS_DI': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                           'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                     ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_MINUS_DM': {'indic_type': '', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                           'method': sma_method_3 + ls_cross_method_3 + tangent_method},
    'indicator_PLUS_DI': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                          'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                    ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_PLUS_DM': {'indic_type': '', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                          'method': sma_method_3 + ls_cross_method_3 + tangent_method},
    'indicator_DPO': {'indic_type': 'price_diff', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]', 'center_point': 0,
                      'method': threshold_mtm_method_1 + sma_method_1 + tangent_method},
    'indicator_ER': {'indic_type': '', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_TII': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + ema_method_2 +
                                ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_PO': {'indic_type': 'return', 'value_range': '[-100, inf]', 'reasonable_range': '[-100, 5000]',
                     'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 + holding_pct + tangent_method},
    'indicator_MADisplaced': {'indic_type': 'price_diff', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]', 'center_point': 0,
                              'method': threshold_mtm_method_1 + sma_method_1 + tangent_method},
    'indicator_POS': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_PAC': {'indic_type': '', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_Qstick': {'indic_type': 'price_diff', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]', 'center_point': 0,
                         'method': threshold_mtm_method_1 + sma_method_1 + tangent_method},
    'indicator_FISHER': {'indic_type': 'ratio_diff', 'value_range': '[-500, 500]', 'reasonable_range': '[-500, 500]',
                         'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_Demakder': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                           'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                     ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_IC': {'indic_type': '', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_TSI': {'indic_type': 'ratio', 'value_range': '[-100, 100]', 'reasonable_range': '[-100, 100]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 + holding_pct + tangent_method},
    'indicator_CLV': {'indic_type': 'ratio', 'value_range': '[-100, 100]', 'reasonable_range': '[-100, 100]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method +
                                ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_WAD': {'indic_type': '', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]', 'center_point': 0,
                      'method': sma_method_1 + tangent_method},
    'indicator_PSY': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_MICD': {'indic_type': '', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_RCCD': {'indic_type': '', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_SI': {'indic_type': 'ratio', 'value_range': '[-100, 100]', 'reasonable_range': '[-100, 100]',
                     'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                               ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_CV': {'indic_type': '', 'value_range': "[0, inf]", 'reasonable_range': '[0, 100]',
                     'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 + holding_pct + tangent_method},
    'indicator_KDJ': {'indic_type': 'ratio_diff', 'value_range': '[-200, 300]', 'reasonable_range': '[-200, 300]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_KDJD': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                       'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                 ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_SKDJ': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                       'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                 ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_SMI': {'indic_type': 'ratio', 'value_range': '[-100, 100]', 'reasonable_range': '[-100, 100]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 + holding_pct + tangent_method},
    'indicator_STC': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_BIAS': {'indic_type': 'return', 'value_range': '[-100, inf]', 'reasonable_range': '[-100, 5000]',
                       'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                 ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_DBCD': {'indic_type': 'return_diff', 'value_range': '[-inf, inf]', 'reasonable_range': '[-100, 100]',
                       'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                 holding_pct + tangent_method},
    'indicator_PPO': {'indic_type': 'return', 'value_range': '[-100, inf]', 'reasonable_range': '[-100, 5000]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 + holding_pct + tangent_method},
    'indicator_ROC': {'indic_type': 'return', 'value_range': '[-100, inf]', 'reasonable_range': '[-100, 5000]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_SROC': {'indic_type': 'return', 'value_range': '[-100, inf]', 'reasonable_range': '[-100, 5000]',
                       'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_KST': {'indic_type': 'return', 'value_range': '[-100, inf]', 'reasonable_range': '[-100, 5000]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 + holding_pct + tangent_method},
    'indicator_COPP': {'indic_type': 'return', 'value_range': '[-100, inf]', 'reasonable_range': '[-100, 5000]',
                       'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_CCI': {'indic_type': '', 'value_range': '[-inf, inf]', 'reasonable_range': '[-500, 500]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method + [indicator_DZCCI]},
    'indicator_WR': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                     'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                               ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_OSC': {'indic_type': 'price_diff', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]',
                      'method': threshold_mtm_method_1 + sma_method_1 + tangent_method},
    'indicator_RSI': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + ema_method_2 +
                                ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method + [indicator_DZRSI, indicator_DO]},
    'indicator_IMI': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_RMI': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    # todo 计算公式还有些问题
    'indicator_RVI': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method +
                                ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_UOS': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_RSIS': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                       'method': threshold_mtm_method_2 + threshold_mtm_reversal_method +
                                 ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_TRIX': {'indic_type': 'return', 'value_range': '[-100, inf]', 'reasonable_range': '[-100, 5000]',
                       'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                 holding_pct + tangent_method},
    'indicator_ULTOSC': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                         'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                   ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_ADTM': {'indic_type': 'ratio_diff', 'value_range': '[-100, 100]', 'reasonable_range': '[-100, 100]',
                       'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                 ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_MABIAS': {'indic_type': 'return', 'value_range': '[-100, inf]', 'reasonable_range': '[-100, 5000]',
                         'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                   ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_BOLL': {'indic_type': 'ratio', 'value_range': '[-inf, inf]', 'reasonable_range': '[-500, 500]',
                       'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_DC': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]',
                     'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_KC': {'indic_type': 'ratio', 'value_range': '[-inf, inf]', 'reasonable_range': '[-500, 500]',
                     'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method + [indicator_FB]},
    'indicator_APZ': {'indic_type': 'ratio', 'value_range': '[-inf, inf]', 'reasonable_range': '[-500, 500]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_HLMA': {'indic_type': '', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_MIKE': {'indic_type': 'ratio', 'value_range': '[-inf, inf]', 'reasonable_range': '[0, 100]',
                       'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_ASI': {'indic_type': '', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]',
                      'method': sma_method_1 + tangent_method},
    'indicator_VR': {'indic_type': 'volume', 'value_range': "[0, inf]", 'reasonable_range': '[0, 500]',
                     'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 + holding_pct + tangent_method},
    'indicator_VRSI': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                       'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                 ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_ARBR_AR': {'indic_type': '', 'value_range': "[0, inf]", 'reasonable_range': '[0, 500]',
                          'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + tangent_method},
    'indicator_ARBR_BR': {'indic_type': '', 'value_range': "[0, inf]", 'reasonable_range': '[0, 500]',
                          'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + tangent_method},
    'indicator_ARBRCROSS': {'indic_type': '', 'value_range': "[-inf, inf]", 'reasonable_range': '[-500, 500]',
                            'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_CR': {'indic_type': '', 'value_range': "[0, inf]", 'reasonable_range': '[0, 500]',
                     'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + tangent_method},
    'indicator_VSTD': {'indic_type': '', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]',
                       'method': sma_method_3 + ls_cross_method_3 + tangent_method},
    'indicator_MAAMT': {'indic_type': 'amount_diff', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]',
                        'method': threshold_mtm_method_1 + sma_method_1 + lsma_method_1 + tangent_method},
    'indicator_SROCVOL': {'indic_type': 'volume_ratio', 'value_range': '[-100, inf]', 'reasonable_range': '[-100, 5000]',
                          'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_PVO': {'indic_type': 'volume_ratio', 'value_range': '[-100, inf]', 'reasonable_range': '[-100, 5000]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_BIASVOL': {'indic_type': 'volume_ratio', 'value_range': '[-100, inf]', 'reasonable_range': '[-100, 5000]',
                          'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                    ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_MACDVOL': {'indic_type': 'volume_diff', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]',
                          'method': threshold_mtm_method_1 + tangent_method},
    'indicator_ROCVOL': {'indic_type': 'volume_ratio', 'value_range': '[-100, inf]', 'reasonable_range': '[-100, 5000]',
                         'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_VWAP': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                       'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_FI': {'indic_type': 'price_diff', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]',
                     'method': ema_method_1 + tangent_method},
    'indicator_NVI': {'indic_type': 'nav', 'value_range': '[0, inf]', 'reasonable_range': '[0, 500]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 + holding_pct + tangent_method},
    'indicator_PVI': {'indic_type': 'nav', 'value_range': '[0, inf]', 'reasonable_range': '[0, 500]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 + holding_pct + tangent_method},
    'indicator_PVT': {'indic_type': 'volume', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]',
                      'method': threshold_mtm_method_1 + sma_method_1 + lsma_method_1 + tangent_method},
    'indicator_VAO': {'indic_type': 'volume', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]',
                      'method': threshold_mtm_method_1 + sma_method_1 + lsma_method_1 + tangent_method},
    'indicator_RSIV': {'indic_type': 'ratio', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                       'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                 ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_AMV': {'indic_type': 'price', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                      'method': sma_method_3 + ls_cross_method_3 + kline_cross_method_1 + tangent_method},
    'indicator_VRAMT': {'indic_type': 'amount', 'value_range': "[0, inf]", 'reasonable_range': '[0, 500]',
                        'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 + holding_pct + tangent_method},
    'indicator_WVAD': {'indic_type': 'volume', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]',
                       'method': threshold_mtm_method_1 + sma_method_1 + tangent_method},
    'indicator_AD': {'indic_type': 'volume', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]',
                     'method': threshold_mtm_method_1 + sma_method_1 + lsma_method_1 + tangent_method},
    'indicator_OBV': {'indic_type': 'volume_diff', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]',
                      'method': threshold_mtm_method_1 + sma_method_1 + lsma_method_1 + tangent_method},
    'indicator_CMF': {'indic_type': 'ratio', 'value_range': '[-100, 100]', 'reasonable_range': '[-100, 100]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_TMF': {'indic_type': 'ratio', 'value_range': '[-100, 100]', 'reasonable_range': '[-100, 100]',
                      'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 +
                                ls_cross_method_2 + ls_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_KO': {'indic_type': 'volume',
                     'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]',
                     'method': threshold_mtm_method_1 + sma_method_1 + tangent_method},
    'indicator_EMV': {'indic_type': 'volume',
                      'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]',
                      'method': threshold_mtm_method_1 + sma_method_1 + lsma_method_1 + tangent_method},
    'indicator_ATR': {'indic_type': 'price_diff', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                      'method': sma_method_3 + ls_cross_method_3 + tangent_method},
    'indicator_NATR': {'indic_type': 'price_diff', 'value_range': '[0, inf]', 'reasonable_range': '[0, 100]',
                       'method': threshold_mtm_method_2 + sma_method_2 + tangent_method},
    'indicator_TRANGE': {'indic_type': 'price_diff', 'value_range': "[0, inf]", 'reasonable_range': '[0, inf]', 'center_point': '',
                         'method': sma_method_3 + lsma_method_3 + tangent_method},
    'indicator_HT_DCPERIOD': {'indic_type': '', 'value_range': '[0, 100]', 'reasonable_range': '[0, 100]',
                              'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + holding_pct + tangent_method},
    'indicator_HT_DCPHASE': {'indic_type': '', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]',
                             'method': threshold_mtm_method_1 + tangent_method},
    'indicator_HT_PHASOR_inphase': {'indic_type': '', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]',
                                    'method': threshold_mtm_method_1 + tangent_method},
    'indicator_HT_PHASOR_quadrature': {'indic_type': '', 'value_range': '[-inf, inf]', 'reasonable_range': '[-inf, inf]',
                                       'method': threshold_mtm_method_1 + tangent_method},
    'indicator_HT_SINE_sine': {'indic_type': 'ratio', 'value_range': '[-100, 100]', 'reasonable_range': '[-100, 100]',
                               'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 + holding_pct + tangent_method},
    'indicator_HT_SINE_leadsine': {'indic_type': 'ratio', 'value_range': '[-100, 100]', 'reasonable_range': '[-100, 100]',
                                   'method': threshold_mtm_method_2 + threshold_mtm_reversal_method + sma_method_2 + holding_pct + tangent_method},
    'indicator_HT_TRENDMODE': {'indic_type': '', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDL2CROWS': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDL3BLACKCROWS': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDL3INSIDE': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDL3LINESTRIKE': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDL3OUTSIDE': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDL3STARSINSOUTH': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDL3WHITESOLDIERS': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLABANDONEDBABY': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLADVANCEBLOCK': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLBELTHOLD': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLBREAKAWAY': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLCLOSINGMARUBOZU': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLCONCEALBABYSWALL': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLCOUNTERATTACK': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLDARKCLOUDCOVER': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLDOJI': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLDOJISTAR': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLDRAGONFLYDOJI': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLENGULFING': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLEVENINGDOJISTAR': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLEVENINGSTAR': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLGAPSIDESIDEWHITE': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLGRAVESTONEDOJI': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLHAMMER': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLHANGINGMAN': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLHARAMI': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLHARAMICROSS': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLHIGHWAVE': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLHIKKAKE': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLHIKKAKEMOD': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLHOMINGPIGEON': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLIDENTICAL3CROWS': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLINNECK': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLINVERTEDHAMMER': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLKICKING': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLKICKINGBYLENGTH': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLLADDERBOTTOM': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLLONGLEGGEDDOJI': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLLONGLINE': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLMARUBOZU': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLMATCHINGLOW': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLMATHOLD': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLMORNINGDOJISTAR': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLMORNINGSTAR': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLONNECK': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLPIERCING': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLRICKSHAWMAN': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLRISEFALL3METHODS': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLSEPARATINGLINES': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLSHOOTINGSTAR': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLSHORTLINE': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLSPINNINGTOP': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLSTALLEDPATTERN': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLSTICKSANDWICH': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLTAKURI': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLTASUKIGAP': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLTHRUSTING': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLTRISTAR': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLUNIQUE3RIVER': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLUPSIDEGAP2CROWS': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']},
    'indicator_CDLXSIDEGAP3METHODS': {'indic_type': 'Morphology', 'value_range': '', 'reasonable_range': '', 'method': ['enumeration']}}

period_list = [1, 3, 6, 10, 15, 20, 30, 40, 60, 80, 100, 120, 140, 160, 200, 250, 300, 400]
short_long_period_list = list(itertools.combinations(period_list, 2))
ma_period_list = [3, 6, 10, 15, 20, 30, 40, 60, 80, 100, 120, 140, 160, 200, 250, 300, 400]
short_long_ma_period_list = list(itertools.combinations(ma_period_list, 2))
tangent_period_list = [3, 6, 10, 15, 20, 25, 30]

if __name__ == '__main__':
    a = get_thereshold_list(value_range="[-100, 100]", threshold_type="4_2")
